import java.io.File;
import java.io.FileOutputStream;
import javax.imageio.ImageIO

import com.oy.shared.lm.graph.Graph;
import com.oy.shared.lm.graph.GraphEdge;
import com.oy.shared.lm.graph.GraphFactory;
import com.oy.shared.lm.graph.GraphGroup;
import com.oy.shared.lm.graph.GraphNode;
import com.oy.shared.lm.out.GRAPHtoDOT;
import com.oy.shared.lm.out.GRAPHtoDOTtoGIF;


/**
 * This graph constructs and generates the graph
 * 
 * Node produces a leaf, edge connects 2 nodes, and a group produces a box around the nodes
 *
 * A Node needs to call: node.setMemberOf(group) to be a part of a group
 * 
 * Usage - look in main() for usage of this class
 * first, call newGraph(name)
 * then, call nodea = newGraphNode(name, caption)
 * then, call nodea.setShapeComponent(), nodea.setShapeBox() etc.  
 * See Graphviz, Linguine maps docs for more on this
 * then, call newGraphEdge(caption, nodea, nodeb)
 */
class Graphviz
{
    Graph graph
    Logger logger = new Logger()

    /*
    public def int RECORD = 0;
    public def int BOX = 1;
    public def int ELLIPSE = 2;
    public def int CIRCLE = 3;
    public def int DIAMOND = 4;
    public def int TRIANGLE = 5;
    public def int INVTRIANGLE = 6;
    public def int HEXAGON = 7;
    public def int OCTAGON = 8;
    public def int PARALLELOGRAM = 9;
    public def int COMPONENT = 10;
    
    // setShapeComponent()
    */


    def newGraph(String caption, boolean rotated)
    {
        this.graph = GraphFactory.newGraph()
        this.graph.getInfo().setCaption(caption)
        if(rotated)
            graph.getInfo().setRotated(rotated)
    }

    def newGraphGroup(String caption)
    {
        GraphGroup gg = graph.addGroup()
        gg.getInfo().setModeOutlined()
        gg.getInfo().setCaption(caption)
        gg.getInfo().setLineColor("lightgrey")

        return gg
    }

    def newGraphNode(String name, String label)
    {
        GraphNode gnode = graph.addNode()
        gnode.getInfo().setCaption(name)

        if(label!=null)
            gnode.getInfo().setLabel(label)
        else
            gnode.getInfo().setLabel(name)

        def color = "cyan"
        gnode.getInfo().setFillColor(color)
        gnode.getInfo().setFontSize(9)
        
        //gnode.getInfo().setShapeComponent()
        
        return gnode
    }

    def newGraphEdge(String caption, GraphNode nodea, GraphNode nodeb)
    {
        GraphEdge edge = graph.addEdge(nodea, nodeb);
        edge.getInfo().setCaption(caption);
        edge.getInfo().setLineColor("lightgrey")
    }

    def genDotFile(String name)
    {
        def dotFileName = "./graphs/" + name + ".dot"

        GRAPHtoDOT.transform(this.graph, new FileOutputStream(new File(dotFileName)))

        return dotFileName;
    }

    def genDotFileInFolder(String name, String folderPath)
    {
        File folder = new File(folderPath)

        //def dotFileName = "./" + folderPath + "/" + name + ".dot"
        def dotFileName = folderPath + "/" + name + ".dot"

        GRAPHtoDOT.transform(this.graph, new FileOutputStream(new File(dotFileName)))

        return dotFileName;
    }

    def genDotImage(String remark, String dotFilePath)
    {
        def imageFilePath = "./imagegraphs/" + new Filename(dotFilePath, new String(java.io.File.separatorChar), '.').filename()+".png"

        def launchStr = "dot -Tpng " + new File(dotFilePath).getCanonicalPath() + " -o " + new File(imageFilePath).getCanonicalPath()
        println "\t|--"+remark+" launching: " + launchStr

        Process p = Runtime.getRuntime().exec(launchStr)
        def int result = p.waitFor()

        if(result!=0)
            logger.error("\t|--" + remark + "ERROR: creating image from DOT file:" + dotFilePath)
        else
            logger.info("\t|--" + remark + "SUCCESS: created image file:"+ imageFilePath + " from DOT file:" + dotFilePath)

        return dotFilePath + ".gif"
    }

    def genDotImageInFolder(String remark, String dotFilePath, String folderPath)
    {
        File folder = new File(folderPath)

        //def imageFilePath = "./" + folderPath + "/" + new Filename(dotFilePath, new String(java.io.File.separatorChar), '.').filename()+".png"
        def imageFilePath = folderPath + "/" + new Filename(dotFilePath, new String(java.io.File.separatorChar), '.').filename()+".png"

        def launchStr = "dot -Tpng " + new File(dotFilePath).getCanonicalPath() + " -o " + new File(imageFilePath).getCanonicalPath()
        println "\t|--"+remark+" launching: " + launchStr

        Process p = Runtime.getRuntime().exec(launchStr)
        def int result = p.waitFor()

        if(result!=0)
            logger.error("\t|--" + remark + "ERROR: creating image from DOT file:" + dotFilePath)
        else
            logger.info("\t|--" + remark + "SUCCESS: created image file:"+ imageFilePath + " from DOT file:" + dotFilePath)

        return dotFilePath + ".gif"
    }

    static void main( args)
    {
        Graphviz ggen = new Graphviz()

        ggen.newGraph("Test graph", true)
        def a = ggen.newGraphNode("a", "a")
        a.getInfo().setShapeComponent()
        def b = ggen.newGraphNode("b", "b")
        ggen.newGraphEdge("ab", a, b)

        def ggroup = ggen.newGraphGroup("testgroup")
        ggroup.getInfo().setModeOutlined()
        ggroup.getInfo().setCaption("testgroup")

        a.setMemberOf(ggroup)
        b.setMemberOf(ggroup)

        def dotFilePath = ggen.genDotFile("test")
        ggen.genDotImage(""+dotFilePath)
    }
}
